
package com.tendory.gpssim;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.location.LocationManager;
import android.os.BatteryManager;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import com.tendory.common.base.RxBus;
import com.tendory.gpssim.activity.MainFragment;
import com.tendory.gpssim.activity.StatusActivity;
import com.tendory.gpssim.evt.EvtLocationError;
import com.tendory.rxlocation.LocationRequester;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

public class PositionProvider {

    private static final String TAG = PositionProvider.class.getSimpleName();

    private static final int MINIMUM_INTERVAL = 1000;

    public interface PositionListener {
        void onPositionUpdate(Position position);
    }

    private final PositionListener listener;

    private final Context context;
    private SharedPreferences preferences;
//    private LocationManager locationManager;

    private String deviceId;
    private long interval;
    private double distance;
    private double angle;

    private Position lastLocation;
    private Disposable posDisposable;

    public PositionProvider(Context context, PositionListener listener) {
        this.context = context;
        this.listener = listener;

        preferences = PreferenceManager.getDefaultSharedPreferences(context);

        deviceId = preferences.getString(MainFragment.KEY_DEVICE, "undefined");
        interval = Long.parseLong(preferences.getString(MainFragment.KEY_INTERVAL, "10")) * 1000;
        distance = Integer.parseInt(preferences.getString(MainFragment.KEY_DISTANCE, "0"));
        angle = Integer.parseInt(preferences.getString(MainFragment.KEY_ANGLE, "0"));
    }

    @SuppressLint("MissingPermission")
    public void startUpdates() {
        try {
//            locationManager.requestLocationUpdates(
//                    getProvider(preferences.getString(MainFragment.KEY_ACCURACY, "medium")),
//                    distance > 0 || angle > 0 ? MINIMUM_INTERVAL : interval, 0, this);
            posDisposable = new LocationRequester().requestLocation()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(loc -> {
                        if (loc != null) {
                            loc.convertToGcj02();
                            Position position = new Position();
                            position.setLatitude(loc.lat);
                            position.setLongitude(loc.lon);
                            position.setTime(loc.timeD);
                            position.setSpeed(loc.speed * 1.943844);
                            position.setCourse(loc.direction);
                            position.setAltitude(loc.acc);
                            position.setDeviceId(deviceId);
                            position.setBattery(getBatteryLevel(context));
                            onLocationChanged(position);
                        }
                    }, throwable -> {
                        Log.e(TAG, "location error");
                        StatusActivity.addMessage("定位错误");
                        throwable.printStackTrace();
                        RxBus.getInstance().post(new EvtLocationError());
                    });
        } catch (RuntimeException e) {
            Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    public static String getProvider(String accuracy) {
        switch (accuracy) {
            case "high":
                return LocationManager.GPS_PROVIDER;
            case "low":
                return LocationManager.PASSIVE_PROVIDER;
            default:
                return LocationManager.NETWORK_PROVIDER;
        }
    }

    private boolean locImmediately = false;
    public void locImmediately() {
        locImmediately = true;
    }

    private void onLocationChanged(Position location) {
        if (location == null) {
            Log.i(TAG, "location nil");
            return;
        }
        long dt = 0;
        double da = 0;
        if (lastLocation != null) {
            dt = location.getTime().getTime() - lastLocation.getTime().getTime();
            Log.e(TAG, "location newCourse:" + location.getCourse() + " oldCourse:" + lastLocation.getCourse());
            da = Math.abs(location.getCourse() - lastLocation.getCourse());
        }
        Log.e(TAG, "location dt:" + dt + " da:" + da);
        if ((lastLocation == null || locImmediately|| dt >= interval || (angle > 0 && da >= angle)
                //|| distance > 0 && location.distanceTo(lastLocation) >= distance
                )) {
            Log.i(TAG, "location new");
            lastLocation = location;
            listener.onPositionUpdate(location);
            locImmediately = false;
        } else {
            Log.i(TAG, "location ignored");
        }
    }

    public void stopUpdates() {
//        locationManager.removeUpdates(this);
        if (posDisposable != null) {
            posDisposable.dispose();
            posDisposable = null;
        }
    }

    public static double getBatteryLevel(Context context) {
        Intent batteryIntent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        if (batteryIntent != null) {
            int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
            int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
            return (level * 100.0) / scale;
        }
        return 0;
    }

}
